package com.youlu.campus.service.pay.impl;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.req.OrderConfirmComputePriceReq;
import com.youlu.campus.entity.VO.res.OrderConfirmComputePriceRes;
import com.youlu.campus.entity.VO.res.OrderConfirmInfoRes;
import com.youlu.campus.entity.ca.GiftCaInfo;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.activity.impl.ActivityPayConfigService;
import com.youlu.campus.service.activity.impl.PlatformOtherActivityService;
import com.youlu.campus.service.ca.CaInfoService;
import com.youlu.campus.service.cache.CacheCaGroupInfoService;
import com.youlu.campus.service.pay.PayV2Service;
import com.youlu.campus.service.pay.UserPurchaseCaService;
import com.youlu.campus.service.postage.PostageTemplateService;
import com.youlu.campus.service.visitor.UserInfoExtendService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class PayV2ServiceImpl implements PayV2Service {
    @Lazy
    @Autowired
    private UserInfoExtendService userInfoExtendService;
    @Lazy
    @Autowired
    private CaInfoService caInfoService;
    @Lazy
    @Autowired
    private ActivityPayConfigService activityPayConfigService;
    @Lazy
    @Autowired
    private ActivityService activityService;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Lazy
    @Autowired
    private PostageTemplateService postageTemplateService;
    @Lazy
    @Autowired
    private PlatformOtherActivityService platformOtherActivityService;
    @Lazy
    @Autowired
    private UserPurchaseCaService userPurchaseCaService;
    @Autowired
    private CacheCaGroupInfoService cacheCaGroupInfoService;

    @Override
    public OrderConfirmInfoRes getOrderConfirmInfo(UserPO userPO, String activityId, String bizType) {
        final String userId = userPO.getId();
        log.info(":>>> 开始获取用户订单确认页信息:{},{}", userId, activityId);
        OrderConfirmInfoRes res = new OrderConfirmInfoRes();
        List<String> gids = userPurchaseCaService.getUserCaGroupId(activityId, userId, userPO.getMobile(), userPO.getOpenId());
        if (CollectionUtils.isNotEmpty(gids)) {
            CaGroupInfo groupInfo = cacheCaGroupInfoService.findById(gids.get(0));
            ActivityUserRecord userRes = platformOtherActivityService.findByOpenidOrMoble(activityId, userPO.getOpenId(), userPO.getMobile(),
                    groupInfo.getTaskBizType());
            res.setMobile(userRes.getMobile());
            res.setUniversityId(userRes.getUniversityId());
            res.setUniversityName(userRes.getUniversityName());
            if (StringUtils.isBlank(userRes.getRecieveName())) {
                res.setName(userRes.getName());
            } else {
                res.setName(userRes.getRecieveName());
            }
            if (StringUtils.isBlank(userRes.getRecieveMobile())) {
                res.setMobile(userRes.getMobile());
            } else {
                res.setMobile(userRes.getRecieveMobile());
            }
            UserInfoExtend infoExtend1 = userInfoExtendService.findByUserId(userId);
            if (StringUtils.isNotBlank(userRes.getProvince())) {
                res.setProvince(userRes.getProvince());
            } else {
                res.setProvince(infoExtend1 == null ? null : infoExtend1.getProvince());
            }
            if (StringUtils.isNotBlank(userRes.getCity())) {
                res.setCity(userRes.getCity());
            } else {
                res.setCity(infoExtend1 == null ? null : infoExtend1.getCity());
            }
            if (StringUtils.isNotBlank(userRes.getArea())) {
                res.setArea(userRes.getArea());
            } else {
                res.setArea(infoExtend1 == null ? null : infoExtend1.getArea());
            }
            if (StringUtils.isNotBlank(userRes.getAddress())) {
                res.setAddress(userRes.getAddress());
            } else {
                res.setAddress(infoExtend1 == null ? null : infoExtend1.getAddress());
            }
            res.setCaUserName(userRes.getName());
        } else {
            UserInfoExtend infoExtend = userInfoExtendService.findByUserId(userId);
            log.info(":>>> 用户的基本信息:{},{}", userId, JSON.toJSONString(res));
            if (Objects.nonNull(infoExtend)) {
                res.setName(infoExtend.getName());
                res.setProvince(infoExtend.getProvince());
                res.setCity(infoExtend.getCity());
                res.setArea(infoExtend.getArea());
                res.setAddress(infoExtend.getAddress());
                res.setMobile(infoExtend.getMobile());
                res.setUniversityId(infoExtend.getUniversityId());
                res.setUniversityName(infoExtend.getUniversityName());
                res.setCaUserName(infoExtend.getName());
            }
        }
        return res;
    }

    /**
     * 计算优惠价格包括：双证补贴、活动券、平台补贴（正对套装）三个部分
     *
     * @param req
     * @return
     */
    @Override
    public OrderConfirmComputePriceRes computPrice(OrderConfirmComputePriceReq req) {
        log.info(":>>> 订单确认页计算价格:{}", JSON.toJSON(req));
        OrderConfirmComputePriceRes res = new OrderConfirmComputePriceRes();
        ActivityInfo activityInfo = activityService.findOne(req.getActivityId());
        PayConfigPage payConfig = activityPayConfigService.findByActivityId(req.getActivityId());
        // 总费用
        Integer totalFee = 0;
        // 原价
        Integer originalTotalFee = 0;
        //补贴费用
        Integer discountFee = 0;
        //优惠券或活动券折扣
        Integer couponDiscountFee = 0;
        //双证补贴
        Integer subsidyOfDoubleCa = 0;
        //邮费,单位分
        Integer expressFee = 0;
        //商品数量
        Integer num = 0;
        Integer caNum = 0;
        Boolean hasCa = Boolean.FALSE;
        Integer couponNum = 0;
        for (CaInfo caInfo : req.getItems()) {
            if (StringUtils.isBlank(caInfo.getId()) || Objects.isNull(caInfo.getNum())) {
                log.info(":>>> 商品ID或者数量为空:{},{}", caInfo.getId(), caInfo.getNum());
                continue;
            }
            CaInfo c = caInfoService.findOne(caInfo.getId());
            HashMap<String, CaInfo> giftMap = new HashMap<>();
            if (Objects.nonNull(c)) {
                res.getItems().add(c);
                if (CollectionUtils.isNotEmpty(c.getGiftItems())) {
                    for (GiftCaInfo g : c.getGiftItems()) {
                        CaInfo gift = caInfoService.findOne(g.getId());
                        if (Objects.nonNull(gift)) {
                            if (!giftMap.containsKey(g.getId())) {
                                gift.setNum(1);
                                giftMap.put(g.getId(), gift);
                            } else {
                                Integer gnum = giftMap.get(g.getId()).getNum() == null ? 1 : giftMap.get(g.getId()).getNum();
                                if (gift.getNum() != null) {
                                    gnum = gnum + 1;
                                }
                                giftMap.get(g.getId()).setNum(gnum);
                            }
                        }
                    }
                    for (String s : giftMap.keySet()) {
                        res.getItems().add(giftMap.get(s));
                    }
                }
            }
            if (2 != c.getItemType()) {
                hasCa = Boolean.TRUE;
            }
            num = num + caInfo.getNum();
            totalFee = totalFee + c.getPrice() * caInfo.getNum();
            if (Objects.nonNull(c.getOriginalPrice())) {
                originalTotalFee = originalTotalFee + c.getOriginalPrice() * caInfo.getNum();
            }
            if (Boolean.TRUE.equals(c.getHasDiscount())) {
                if (Objects.nonNull(c.getDiscountFee())) {
                    discountFee = discountFee + c.getDiscountFee() * caInfo.getNum();
                }
            }
            if (Boolean.TRUE.equals(c.getHasActivityCoupon())) {
                if (Objects.nonNull(c.getActivityCouponNum()) && Objects.nonNull(c.getActivityCouponFee())) {
                    couponDiscountFee = couponDiscountFee + c.getActivityCouponNum() * c.getActivityCouponFee() * caInfo.getNum();
                }
                couponNum = couponNum + c.getActivityCouponNum();
            }
            if (Boolean.TRUE.equals(c.getDoCaSubsidy()) && Objects.nonNull(c.getItemType()) && 2 != c.getItemType().intValue()) {
                caNum++;
            }
            if (Objects.nonNull(caInfo.getExpressFee())) {
                expressFee = expressFee + caInfo.getExpressFee();
            }
        }
        // 处理双证补贴
        if (Objects.nonNull(payConfig)) {
            if (Boolean.TRUE.equals(hasCa) && Boolean.TRUE.equals(payConfig.getOpenCaSubsidy())) {
                if (caNum >= payConfig.getCaSubsidyThreshold()) {
                    subsidyOfDoubleCa = payConfig.getCaSubsidyFee();
                }
            }
        }
        if (Objects.nonNull(payConfig)) {
            PostageTemplate postageTemplate = null;
            if (Objects.nonNull(payConfig) && StringUtils.isNotBlank(payConfig.getPostageTemplateId())) {
                postageTemplate = postageTemplateService.findOne(payConfig.getPostageTemplateId());
                HashMap<String, Integer> exMap = this.getOrderExpreeFee(postageTemplate, req.getProvince(), expressFee);
                res.setExpressFee(exMap.get("fee"));
                res.setExtraExpressFee(exMap.get("extraFee"));
                res.setExpressDesc(postageTemplate.getExpressDesc());
                res.setExpressFeeTips(postageTemplate.getExpressFeeTips());
                if (Objects.nonNull(res.getExpressFee()) && (res.getExpressFee().compareTo(0) == 1)) {
                    totalFee = totalFee + res.getExpressFee();

                }
                if (Objects.nonNull(res.getExtraExpressFee()) && (res.getExtraExpressFee().compareTo(0) == 1)) {
                    totalFee = totalFee + res.getExtraExpressFee();

                }

            }
        }
        res.setTotalFee(totalFee - subsidyOfDoubleCa);
        res.setOriginalTotalFee(originalTotalFee);
        res.setDiscountFee(discountFee);
        res.setCouponDiscountFee(couponDiscountFee);
        res.setNum(num);
        res.setSubsidyOfDoubleCa(subsidyOfDoubleCa);
        res.setHasCa(hasCa);
        res.setCouponNum(couponNum);
        if (Objects.nonNull(activityInfo)) {
            res.setTips(activityInfo.getOrderTips());
        }
        log.info(":>>> 订单确认页计算价格结果:{}", JSON.toJSON(res));
        return res;
    }

    /* 计算邮费
     *
     * @param postageTemplate
     * @param province
     * @param expreeFee
     * @return
     */
    private HashMap<String, Integer> getOrderExpreeFee(PostageTemplate postageTemplate, String province,
                                                       Integer expreeFee) {
        log.info(":>>> 开始获取省:{},邮费:{},模版:{}", province, expreeFee, JSON.toJSONString(postageTemplate));
        HashMap<String, Integer> res = new HashMap<>();
        if (StringUtils.isBlank(province) || Objects.isNull(postageTemplate)) {
            log.error(":>>> 下单参数错误:省或证书邮费配置为空");
            res.put("fee", 0);
            res.put("extraFee", 0);
//            throw new BusinessException("请联系客服领取!");
        }
        Integer fee = 0;
        Integer extraFee = 0;
        Query query = new Query().addCriteria(Criteria.where("postageTemplateId").is(postageTemplate.getId()).and(
                "province").is(province));
        PostageTemplateDetail p = mongoTemplate.findOne(query, PostageTemplateDetail.class);
        log.info(">>> 偏远地区邮费:{}", JSON.toJSONString(p));
        if (Objects.nonNull(p)) {
            extraFee = p.getPrice().intValue();

        }
        if (Objects.nonNull(expreeFee)) {
            if (expreeFee.compareTo(0) == 1) {
                fee = expreeFee;
            } else {
                fee = postageTemplate.getPrice().intValue();
            }

        } else {
            fee = postageTemplate.getPrice().intValue();
        }
        res.put("fee", fee);
        res.put("extraFee", extraFee);
        return res;
    }
}
